package org.kymjs.kjframe.utils;

import static android.content.ContentValues.TAG;
import static org.kymjs.kjframe.common.Constant.HEADER_AUTH_KEY;
import static org.kymjs.kjframe.common.Constant.WS_BASE;

import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.media.projection.MediaProjection;
import android.os.Build;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.json.JSONException;
import org.json.JSONObject;
import org.kymjs.kjframe.common.Constant;
import org.webrtc.DataChannel;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpReceiver;
import org.webrtc.ScreenCapturerAndroid;
import org.webrtc.SdpObserver;
import org.webrtc.SessionDescription;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoFrame;
import org.webrtc.VideoSink;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;

import java.util.Collections;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicLong;

import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;

public class WebrtcClient {

    private PeerConnectionFactory peerConnectionFactory;
    private PeerConnection peerConnection;
    private WebsocketClient wsClient;
    private VideoCapturer screenCapturer;

    private VideoTrack videoTrack;

    private String wsUrl;
    private final EglBase eglBase;

    public WebrtcClient(Context context, Intent mediaProjectionIntent, String inviteCode, String token) {
        wsUrl = String.format("%s/room/websocket?%s=%s", WS_BASE, HEADER_AUTH_KEY, token);
        eglBase = EglBase.create();  // 只创建一次c
        initPeerConnectionFactory(context);
        createPeerConnection();
        initScreenCapturer(context, mediaProjectionIntent);
        initWebSocket();
//        createAndSendOffer();
    }

    // 1. 初始化 PeerConnectionFactory
    private void initPeerConnectionFactory(Context context) {
        PeerConnectionFactory.InitializationOptions options =
                PeerConnectionFactory.InitializationOptions.builder(context)
                        .createInitializationOptions();
        PeerConnectionFactory.initialize(options);

        peerConnectionFactory = PeerConnectionFactory.builder()
                .setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
                .setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(), true, true))
                .createPeerConnectionFactory();
    }

    // 2. 创建 PeerConnection，设置监听
    private void createPeerConnection() {
        // List<PeerConnection.IceServer> iceServers = new ArrayList<>();
        // iceServers.add(PeerConnection.IceServer.builder("stun:relay.metered.ca:80").createIceServer());
        // iceServers.add(PeerConnection.IceServer.builder("turn:relay.metered.ca:80")
        //        .setUsername("f656bb327ada11408d2cd592")
        //        .setPassword("D5FTwyiln3XE0vFq")
        //        .createIceServer());

        // 不设置任何 ICE Server，peerConnection 会默认只使用 host candidate，直接内网连接
        PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(Collections.emptyList());
        rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;

        peerConnection = peerConnectionFactory.createPeerConnection(rtcConfig, new PeerConnectionObserver());
    }
    private void initScreenCapturer(Context context, Intent mediaProjectionPermissionResultData) {
        screenCapturer = new ScreenCapturerAndroid(
                mediaProjectionPermissionResultData,
                new MediaProjection.Callback() {
                    @Override
                    public void onStop() {
                        Log.d("WebrtcClient", "MediaProjection stopped");
                    }
                });

        HandlerThread handlerThread = new HandlerThread("WebRTC-Capture");
        handlerThread.start();

        SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create(
                "WebRTC-Capture",
                eglBase.getEglBaseContext()
        );


        VideoSource videoSource = peerConnectionFactory.createVideoSource(false);
        screenCapturer.initialize(surfaceTextureHelper, context, videoSource.getCapturerObserver());
        screenCapturer.startCapture(720, 1280, 30);

        videoTrack = peerConnectionFactory.createVideoTrack("ARDAMSv0", videoSource);
        System.out.println("成功添加轨道了");
        System.out.println(videoTrack);
        if (videoTrack != null) {
            Log.d(TAG, "VideoTrack 创建成功");
        } else {
            Log.e(TAG, "VideoTrack 创建失败");
        }
        AtomicLong lastFrameTime = new AtomicLong(System.currentTimeMillis());

//        videoTrack.addSink(frame -> {
//            lastFrameTime.set(System.currentTimeMillis());
//            Log.d(TAG, "收到视频帧: " + frame.getBuffer().getWidth() + "x" + frame.getBuffer().getHeight());
//        });

        // 每 3 秒检查一次是否还在采集帧
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if (System.currentTimeMillis() - lastFrameTime.get() > 3000) {
                    Log.e(TAG, "帧已停止更新，考虑重启采集");
                }
            }
        }, 0, 3000);
        if (peerConnection != null) {
            // 👇 正确添加方式，包含 MediaStream ID
            peerConnection.addTrack(videoTrack, Collections.singletonList("ARDAMS"));
        } else {
            Log.e(TAG, "peerConnection 为 null，不能添加 track");
        }
    }



    // 3. 初始化 WebSocket 并连接信令服务器
    private void initWebSocket() {
        System.out.println(wsUrl);
        wsClient = new WebsocketClient(wsUrl, new WebSocketListener() {
            @Override
            public void onClosed(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
                super.onClosed(webSocket, code, reason);
                System.out.println("关闭ws连接");
            }

            @Override
            public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, @Nullable Response response) {
                super.onFailure(webSocket, t, response);
                System.out.println("ws连接失败");
                System.out.println("失败原因：" + response);
            }

            @Override
            public void onOpen(@NonNull WebSocket webSocket, @NonNull Response response) {
                super.onOpen(webSocket, response);
                System.out.println("ws连接开启");
            }

            @Override
            public void onMessage(@NonNull WebSocket webSocket, @NonNull String text) {
                super.onMessage(webSocket, text);
                System.out.println("ws接收到了消息");
                System.out.println(text);
                onSignalMessage(text);
            }
        });
    }

    // 5. 处理信令服务器消息
    private void onSignalMessage(String message) {
        try {
            JSONObject json = new JSONObject(message);
            String type = json.getString("type");
            JSONObject data = json.getJSONObject("data");

            switch (type) {
                case "sdp":
                    if (!data.has("sdp")) {
                        Log.e(TAG, "offer SDP missing");
                        return;
                    }
                    SessionDescription offerDesc = new SessionDescription(
                            SessionDescription.Type.OFFER,
                            data.getString("sdp"));
                    peerConnection.setRemoteDescription(new SdpObserver() {
                        @Override
                        public void onCreateSuccess(SessionDescription sessionDescription) {}

                        @Override
                        public void onCreateFailure(String s) {}

                        @Override
                        public void onSetFailure(String s) {}

                        @Override
                        public void onSetSuccess() {
                            Log.d(TAG, "setRemoteDescription success");
                            // 添加轨道
//                            peerConnection.addTrack(videoTrack, Collections.singletonList("ARDAMS"));
                            videoTrack.setEnabled(true);
                            // 创建answer
                            peerConnection.createAnswer(new SdpAdapter("createAnswer") {
                                @Override
                                public void onCreateSuccess(SessionDescription sessionDescription) {
                                    peerConnection.setLocalDescription(this, sessionDescription);
                                    // 发送answer消息
                                    try {
                                        JSONObject answerMsg = new JSONObject();
                                        answerMsg.put("type", "sdp");
                                        JSONObject answerData = new JSONObject();
                                        answerData.put("type", "answer");
                                        answerData.put("sdp", sessionDescription.description);
                                        answerMsg.put("data", answerData.toString());
                                        wsClient.sendMessage(answerMsg.toString());
                                    } catch (JSONException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }, new MediaConstraints());
                        }
                        // 其他回调空实现
                    }, offerDesc);
                    break;

                case "answer":
                    if (!data.has("sdp")) {
                        Log.e(TAG, "answer SDP missing");
                        return;
                    }
                    SessionDescription answerDesc = new SessionDescription(
                            SessionDescription.Type.ANSWER,
                            data.getString("sdp"));
                    peerConnection.setRemoteDescription(new SdpAdapter("setRemoteDesc"), answerDesc);
                    break;

                case "ice":
                    if (!data.has("candidate") ||
                            !data.has("sdpMid") ||
                            !data.has("sdpMLineIndex")) {
                        Log.e(TAG, "candidate info missing");
                        return;
                    }
                    IceCandidate iceCandidate = new IceCandidate(
                            data.getString("sdpMid"),
                            data.getInt("sdpMLineIndex"),
                            data.getString("candidate"));
                    peerConnection.addIceCandidate(iceCandidate);
                    break;

                default:
                    break;
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private void sendMessage(IceCandidate candidate) {
        JSONObject candidateJson = new JSONObject();
        try {
            candidateJson.put("sdpMid", candidate.sdpMid);
            candidateJson.put("sdpMLineIndex", candidate.sdpMLineIndex);
            candidateJson.put("candidate", candidate.sdp);

            JSONObject message = new JSONObject();
            message.put("type", "ice");
            message.put("data", candidateJson.toString());  // ✅ 关键是这里，转成字符串

            wsClient.sendMessage(message.toString());
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    // --- PeerConnection Observer ---
    private class PeerConnectionObserver implements PeerConnection.Observer {
        @Override
        public void onIceConnectionReceivingChange(boolean b) {

        }

        @Override
        public void onAddStream(MediaStream mediaStream) {

        }

        @Override
        public void onIceCandidate(IceCandidate candidate) {
            // 收集到本地ICE candidate，发送给远端
            sendMessage(candidate);
        }

        @Override
        public void onIceConnectionChange(PeerConnection.IceConnectionState newState) {
            System.out.println("ICE state: " + newState);
        }

        @Override
        public void onConnectionChange(PeerConnection.PeerConnectionState newState) {
            System.out.println("PeerConnection state: " + newState);
        }

        // 其他方法可以空实现
        @Override public void onSignalingChange(PeerConnection.SignalingState signalingState) {}
        @Override public void onIceCandidatesRemoved(IceCandidate[] candidates) {}
        @Override public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {}
        @Override
        public void onRemoveStream(MediaStream mediaStream) {}

        @Override
        public void onDataChannel(DataChannel dataChannel) {

        }

        @Override
        public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {
            System.out.println("视频流获取成功");
        }

        @Override public void onRenegotiationNeeded() {}
    }

    // --- WebSocket Listener ---
    private class SignalingWebSocketListener extends WebSocketListener {
        @Override
        public void onOpen(WebSocket webSocket, Response response) {
            System.out.println("WebSocket Connected");
        }

        @Override
        public void onMessage(WebSocket webSocket, String text) {
            onSignalMessage(text);
        }

        @Override
        public void onClosed(WebSocket webSocket, int code, String reason) {
            System.out.println("WebSocket Closed: " + reason);
        }

        @Override
        public void onFailure(WebSocket webSocket, Throwable t, Response response) {
            System.err.println("WebSocket Error: " + t.getMessage());
        }
    }

    // --- SDP Adapter简化实现 ---
    private class SdpAdapter implements SdpObserver {
        private String tag;

        SdpAdapter(String tag) {
            this.tag = tag;
        }

        @Override
        public void onCreateSuccess(SessionDescription sessionDescription) {}

        @Override
        public void onSetSuccess() {
            System.out.println(tag + " onSetSuccess");
        }

        @Override
        public void onCreateFailure(String s) {
            System.err.println(tag + " onCreateFailure: " + s);
        }

        @Override
        public void onSetFailure(String s) {
            System.err.println(tag + " onSetFailure: " + s);
        }
    }
}
